package com.source.multithread.randomaccesscopyfile;

import java.io.File;
   import java.io.FileNotFoundException;
   import java.io.IOException;
   import java.io.RandomAccessFile;
   import java.util.concurrent.TimeUnit;
   /**
    * https://www.cnblogs.com/five-five/p/13819366.html
    * https://www.cnblogs.com/five-five/p/13819366.html
   * @作者 five-five
   * @创建时间 2020/10/15
   */
  public class DownloadUtil {
      private File fromFile;//源文件
      private File toFile;//要拷贝到的地方
      private int threadNum;//线程数量
  
      //下载的方法
      public void doDownLoad() {
          System.out.println(fromFile.length());
          for (int i=0;i<threadNum;i++){
              MydownLoadThread thread = new MydownLoadThread(i);
              thread.setName("线程"+(i+1));
              System.out.println(thread.getName()+"的任务量是\t"+thread.getBlockSize());
              thread.start();
          }
         System.out.println("文件上传完毕");
      }
  
      public DownloadUtil() {
      }
 
      public DownloadUtil(File fromFile, File toFile, int threadNum) {
          this.fromFile = fromFile;
          this.toFile = toFile;
          this.threadNum = threadNum;
      }
  
      class MydownLoadThread extends Thread {
  
          private volatile int index;//表示第几个线程

       /*   private long blockSize = fromFile.length() % threadNum == 0
                  ? fromFile.length() / threadNum
                  : fromFile.length() / threadNum + (fromFile.length() % threadNum); //每个线程下载的文件大小*/

          private long blockSize = fromFile.length() % threadNum == 0
                  ? fromFile.length() / threadNum
                  : fromFile.length() / threadNum + (fromFile.length() % threadNum); //每个线程下载的文件大小

          private volatile long startPos;//起始位置
  
          /**
           * 第多少个线程
           *
           * @param index
           */
          public MydownLoadThread(int index) {
              this.index = index;
              startPos = index * blockSize;//计算下载了多少
          }
  
          @Override
          public void run() {
              RandomAccessFile rf = null;
              RandomAccessFile wf = null;
             try {
  //                System.out.println("起始位置"+startPos);
                  //"r", "rw", "rws", or "rwd"
                  rf = new RandomAccessFile(fromFile, "r");//只读
                  wf = new RandomAccessFile(toFile, "rw");//只写
                  rf.seek(startPos);
                  wf.seek(startPos);
                  byte[] buf = new byte[1024 * 1024];//缓存区为1MB
                  int len = -1;
                  do {
                      //记录每次读取的大小(缓冲区可能大于线程任务量)
                      len = blockSize > buf.length ? buf.length : (int) blockSize;
                      //io操作
                      rf.read(buf, 0, len);
                      wf.write(buf, 0, len);
                      blockSize -= len;
                      System.out.println(Thread.currentThread().getName() + "读取了" + len + "个字节");
                 } while (blockSize>0);
                  wf.close();
                  rf.close();
  //                TimeUnit.SECONDS.sleep(1);//每次睡一秒
              } catch (Exception e) {
                 e.printStackTrace();
              }
         }
  
          public int getIndex() {
              return index;
          }
  
          public void setIndex(int index) {
              this.index = index;
          }
  
          public long getBlockSize() {
              return blockSize;
          }
  
          public void setBlockSize(long blockSize) {
             this.blockSize = blockSize;
         }
 
         public long getStartPos() {
             return startPos;
         }
 
         public void setStartPos(long startPos) {
             this.startPos = startPos;
         }
     }
 
     public File getFromFile() {
         return fromFile;
     }
 
     public void setFromFile(File fromFile) {
         this.fromFile = fromFile;
     }
 
     public File getToFile() {
         return toFile;
     }
 
     public void setToFile(File toFile) {
         this.toFile = toFile;
     }
 
     public int getThreadNum() {
         return threadNum;
     }
 
     public void setThreadNum(int threadNum) {
         this.threadNum = threadNum;
     }
 }